package leetcode; /**
 * description:
 * author:张腾
 * date:2021-06-27
 */

/**
 *
 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中，返回 true ；否则，返回 false 。

 单词必须按照字母顺序，通过相邻的单元格内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
 */
public class leetcode79 {
    private static final int[][] DIRECTIONS = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
    private int rows;
    private int cols;
    private int len;
    private boolean[][] visited;
    private char[] charArray;
    private char[][] board;

    public boolean exist(char[][] board, String word) {
        rows = board.length;
        if (rows==0) return false;
        cols = board[0].length;
        this.len = word.length();
        this.board = board;
        this.charArray = word.toCharArray();
        visited = new boolean[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (dfs(i,j,0)) return true;
            }
        }
        return false;
    }

    private boolean dfs(int x,int y,int begin){
        if (begin==len-1) return board[x][y] == charArray[begin];
        if (board[x][y] == charArray[begin]){
            visited[x][y] = true;
            for (int[] direction : DIRECTIONS) {
                int newX = x+direction[0];
                int newY = y+direction[1];
                if (inArea(newX,newY) && !visited[newX][newY]){
                    if (dfs(newX,newY,begin+1)) return true;
                }
            }
            visited[x][y] = false;
        }
        return false;
    }

    private boolean inArea(int x,int y){
        return x>=0 && x<rows && y>=0 && y<cols;
    }
}
